package de.jensklingenberg.ktorfit.poetspec

import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.TypeSpec
import de.jensklingenberg.ktorfit.model.ClassData
import de.jensklingenberg.ktorfit.model.converterHelper
import de.jensklingenberg.ktorfit.model.ktorfitClass
import de.jensklingenberg.ktorfit.model.providerClass
import de.jensklingenberg.ktorfit.model.toClassName
import de.jensklingenberg.ktorfit.utils.addImports

fun createFileSpec(
    classData: ClassData,
    implClassName: String,
    implClassSpec: TypeSpec
): FileSpec {
    val suppressAnnotation =
        AnnotationSpec
            .builder(Suppress::class)
            .addMember("\"warnings\"")
            .build()

    val providerClass =
        createProviderClassSpec(classData)
    val createExtensionFunctionSpec = getCreateExtensionFunctionSpec(classData)

    return FileSpec
        .builder(classData.packageName, implClassName)
        .addAnnotation(suppressAnnotation)
        .addFileComment("Generated by Ktorfit")
        .addImports(classData.imports)
        .addTypes(listOf(implClassSpec, providerClass))
        .addFunction(createExtensionFunctionSpec)
        .build()
}

private fun createProviderClassSpec(classData: ClassData) =
    TypeSpec
        .classBuilder(classData.providerName)
        .addModifiers(classData.modifiers)
        .addSuperinterface(
            providerClass.toClassName().parameterizedBy(ClassName(classData.packageName, classData.name)),
        ).addFunction(
            FunSpec
                .builder("create")
                .addModifiers(KModifier.OVERRIDE)
                .addParameter(ktorfitClass.objectName, ktorfitClass.toClassName())
                .addStatement("return ${classData.implName}(${ktorfitClass.objectName}.baseUrl, ${ktorfitClass.objectName}.httpClient, ${converterHelper.name}(${ktorfitClass.objectName}))")
                .returns(ClassName(classData.packageName, classData.name))
                .build(),
        ).build()

/**
 * public fun Ktorfit.createExampleApi(): ExampleApi = this.create(_ExampleApiImpl()
 */
private fun getCreateExtensionFunctionSpec(classData: ClassData): FunSpec =
    FunSpec
        .builder("create${classData.name}")
        .addModifiers(classData.modifiers)
        .addStatement("return ${classData.implName}(this.baseUrl, this.httpClient, ${converterHelper.name}(this))")
        .receiver(ktorfitClass.toClassName())
        .returns(ClassName(classData.packageName, classData.name))
        .build()
